#include <QDebug>

#include "mapparser.h"
#include "utilxmlparser.h"
#include "mapinfo.h"

#define OLDVERDATESPACE 4


MapParser::MapParser()
{

}

MapParser::~MapParser()
{
    if (m_pRwXml != nullptr)
    {
        delete m_pRwXml;
        m_pRwXml = nullptr;
    }
}

bool MapParser::loadMapFromFile(const std::string &strMapFileName)
{
    m_pRwXml = new RwXml(strMapFileName.c_str());
    if (nullptr == m_pRwXml->getDoc())
    {
        qDebug() << "fail to load file" << strMapFileName.c_str() << endl;

        return false;
    }

    // root node
    const TiXmlElement *pRootNode = m_pRwXml->getRootElement();
    if (nullptr == pRootNode)
    {
        std::string strErrMsg = "xml no root node";
        return false;
    }

    // header
    Header header;
    bool bNewVersion = true; // 兼容8字地图，布尔值表示默认为1.4H版本
    int iRet = parseHeader(*pRootNode, header, bNewVersion);

    // roads
    QVector<SRoad> vecRoad;
    iRet += parseRoad(*pRootNode, vecRoad);

    // controller
    QVector<SController> vecController;
    iRet += parseController(*pRootNode, vecController);

    // junction
    QVector<Junction> vecJunction;
    iRet += parserJunction(*pRootNode, vecJunction);

    if (iRet != 0)
    {
        std::string strErrMsg = "xml parse is error";
        return false;
    }

    __MAPDATA->setHeader(header);
    __MAPDATA->setRoad(vecRoad);
    __MAPDATA->setController(vecController);
    __MAPDATA->setJunction(vecJunction);

    return true;
}

int MapParser::parseHeader(const TiXmlElement &xmlNode, Header &header, bool &bNewVersion)
{
    const TiXmlElement *pHeaderNode = xmlNode.FirstChildElement(XML_HEADER);
    if (nullptr == pHeaderNode)
    {
        std::string strErrMsg = "xml data missing header";
        return -1;
    }

    std::string strDate;
    std::string strDatabaseName;
    std::string strRevMajor;
    std::string strRevMinor;
    std::string strVendor;
    std::string strVersion;
    double dEast = 0.0;
    double dNorth = 0.0;
    double dSouth = 0.0;
    double dWest = 0.0;

    int iChecker = UtilXmlParser::queryStringAttribute(*pHeaderNode, XML_DATE, strDate);
    int iStrDateSpaceNum = count(strDate.begin(), strDate.end(), ' ');
    // date不是按1.4H规范命名
    if(OLDVERDATESPACE == iStrDateSpaceNum)
    {
        bNewVersion = false;
    }

    iChecker += UtilXmlParser::queryStringAttribute(*pHeaderNode, XML_NAME, strDatabaseName);
    iChecker += UtilXmlParser::queryStringAttribute(*pHeaderNode, XML_REVMAJOR, strRevMajor);
    iChecker += UtilXmlParser::queryStringAttribute(*pHeaderNode, XML_REVMINOR, strRevMinor);

    if(bNewVersion)
    {
        iChecker += UtilXmlParser::queryStringAttribute(*pHeaderNode, XML_VENDOR, strVendor);
    }

    iChecker += UtilXmlParser::queryStringAttribute(*pHeaderNode, XML_VERSION, strVersion);
    iChecker += pHeaderNode->QueryDoubleAttribute(XML_EAST, &dEast);
    iChecker += pHeaderNode->QueryDoubleAttribute(XML_NORTH, &dNorth);
    iChecker += pHeaderNode->QueryDoubleAttribute(XML_SOUTH, &dSouth);
    iChecker += pHeaderNode->QueryDoubleAttribute(XML_WEST, &dWest);

    if (iChecker != TIXML_SUCCESS)
    {
        std::string strErrMsg = "Error parsing header attributes";
        return -1;
    }

    header.date = strDate;
    header.name = strDatabaseName;
    header.revMajor = strRevMajor;
    header.revMinor = strRevMinor;
    header.vendor = strVendor;
    header.version = strVersion;
    header.east = dEast;
    header.north = dNorth;
    header.south = dSouth;
    header.west = dWest;

    const TiXmlElement *pGeoReferenceNode = pHeaderNode->FirstChildElement(XML_GEO);
    if (nullptr == pGeoReferenceNode)
    {
        std::string strErrMsg = "Error parsing header geoReoference attributes";
        //return -1;
    }
    else
    {
        const TiXmlText* pGeoText = pGeoReferenceNode->FirstChild()->ToText();
        if (nullptr == pGeoText)
        {
            std::string strErrMsg = "Error parsing header geoReoference text";
            //return -1;
        }

        // coordinate frame
        std::string strFromCoordinate = pGeoText->Value();
        header.geoReference = strFromCoordinate;

        int iEastZone = getLongitudeZone(dEast);
        int iWestZone = getLongitudeZone(dWest);
        //    if (iEastZone != iWestZone)
        //    {
        //        std::string strErrMsg = "unsupport data in more than one zones";
        //        return -1;
        //    }

        int iZone = iWestZone;
        std::string strCoordinate = "+proj=utm +zone=" +
                std::to_string(iZone) +
                " +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
        // 遗留坐标系转换
    }

    return 0;
}

// 获取经度区域
int MapParser::getLongitudeZone(double dLongitude)
{
    double dLongitudeZone = 0.0;

    if (dLongitude < 0.0)
    {
        dLongitudeZone = ((180.0 + dLongitude) / 6.0) + 1;
    }
    else
    {
        dLongitudeZone = (dLongitude / 6.0) + 31;
    }

    return static_cast<int>(dLongitudeZone);
}

bool MapParser::bRoadBelongToJunction(const std::string &strRoadID)
{
    if(strRoadID.empty())
    {
        return false;
    }

    return strRoadID != "-1";
}

int MapParser::parseRoad(const TiXmlElement &xmlNode, QVector<SRoad> &vecRoad)
{
    const TiXmlElement *pRoadNode = xmlNode.FirstChildElement(XML_ROAD);
    while (pRoadNode != nullptr)
    {
        // road attribute
        std::string strID;
        std::string strRoadName;
        std::string strJunctionID;
        double dLength = 0.0;

        int iChecker = UtilXmlParser::queryStringAttribute(*pRoadNode, XML_ID, strID);
        iChecker += UtilXmlParser::queryStringAttribute(*pRoadNode, XML_NAME, strRoadName);
        iChecker += UtilXmlParser::queryStringAttribute(*pRoadNode, XML_JUNCTION, strJunctionID);
        iChecker += pRoadNode->QueryDoubleAttribute(XML_LENGTH, &dLength);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "Error parsing road attributes";
            return -1;
        }

        SRoad road;
        road.id = strID;
        road.name = strRoadName;

        if (bRoadBelongToJunction(strJunctionID))
        {
            road.junction = strJunctionID;
        }

        road.length = dLength;

        // link
        RoadLink roadLink;
        int iRet = parseRoadLink(*pRoadNode, roadLink);

        // type
        RoadType roadType;
        iRet += parseRoadType(*pRoadNode, roadType);

        // planView
        PlanView planView;
        iRet += parsePlanView(*pRoadNode, planView);

        // elevationProfile
        ElevationProfile elevationProfile;
        iRet += parseElevationProfile(*pRoadNode, elevationProfile);

        // lanes
        Lanes lanes;
        iRet += parseRoadLanes(*pRoadNode, lanes);

        // objects
        Objects objects;
        iRet += parseRoadObjects(*pRoadNode, objects);

        // signals
        Signals roadSignals;
        iRet += parseRoadSignals(*pRoadNode, roadSignals);

        if (iRet != 0)
        {
            std::string strErrMsg = "Error parsing road";
            return -1;
        }

        road.roadLink = roadLink;
        road.roadType = roadType;
        road.planView = planView;
        road.elevationProfile = elevationProfile;
        road.lanes = lanes;
        road.objects = objects;
        road.roadSignals = roadSignals;

        vecRoad.push_back(road);

        pRoadNode = pRoadNode->NextSiblingElement(XML_ROAD);
    }

    return 0;
}

int MapParser::parseRoadLinkRelat(const TiXmlElement &xmlNode, LinkParameter &linkParameter)
{
    std::string strContactPoint;
    std::string strElementRoadId;
    std::string strElementType;

    int iChecker = UtilXmlParser::queryStringAttribute(xmlNode, XML_CONTACTPOINT, strContactPoint);
    iChecker += UtilXmlParser::queryStringAttribute(xmlNode, XML_ELEMENTID, strElementRoadId);
    iChecker += UtilXmlParser::queryStringAttribute(xmlNode, XML_ELEMENTTYPE, strElementType);

    if (iChecker != TIXML_SUCCESS)
    {
        std::string strErrMsg = "Error parsing road link node relat";
//        return -1;  // 兼容8字地图
    }

    linkParameter.contactPoint = strContactPoint;
    linkParameter.elementId = strElementRoadId;
    linkParameter.elementType = strElementType;

    return 0;
}

int MapParser::parseRoadLink(const TiXmlElement &xmlNode, RoadLink &roadLink)
{
    const TiXmlElement *pRoadLinkNode = xmlNode.FirstChildElement(XML_LINK);
    while (pRoadLinkNode != nullptr)
    {
        const TiXmlElement *pRoadLinkPreNode = pRoadLinkNode->FirstChildElement(XML_PREDECESSOR);
        int iChecker = TIXML_SUCCESS;
        if (nullptr == pRoadLinkPreNode)
        {
            std::string strErrMsg = "road link pre node is null";
        }
        else
        {
            iChecker += parseRoadLinkRelat(*pRoadLinkPreNode, roadLink.predecessor);
        }

        const TiXmlElement *pRoadLinkSucNode = pRoadLinkNode->FirstChildElement(XML_SUCCESSOR);
        if (nullptr == pRoadLinkSucNode)
        {
            std::string strErrMsg = "road link suc node is null";
        }
        else
        {
            iChecker += parseRoadLinkRelat(*pRoadLinkSucNode, roadLink.successor);
        }

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "Error parsing road link";
            return -1;
        }

        pRoadLinkNode = pRoadLinkNode->NextSiblingElement(XML_LINK);
    }

    return 0;
}

int MapParser::parseRoadType(const TiXmlElement &xmlNode, RoadType &roadType)
{
    const TiXmlElement *pRoadTypeNode = xmlNode.FirstChildElement(XML_TYPE);
    while (pRoadTypeNode != nullptr)
    {
        std::string strRoadTypeS;
        std::string strRoadType;

        int iChecker = UtilXmlParser::queryStringAttribute(*pRoadTypeNode, XML_S, strRoadTypeS);
        iChecker += UtilXmlParser::queryStringAttribute(*pRoadTypeNode, XML_TYPE, strRoadType);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "road type node is error";
            return -1;
        }

        roadType.s = strRoadTypeS;
        roadType.type = strRoadType;

        pRoadTypeNode = pRoadTypeNode->NextSiblingElement(XML_TYPE);
    }

    return 0;
}

int MapParser::parseGeometry(const TiXmlElement &xmlNode, QVector<SGeometry> &vecGeometry)
{
    const TiXmlElement *pGeometryNode = xmlNode.FirstChildElement(XML_GEOMETRY);
    while (pGeometryNode != nullptr)
    {
        double dHdg =0.0;
        double dLength = 0.0;
        double dS = 0.0;
        double dX = 0.0;
        double dY = 0.0;

        int iChecker = pGeometryNode->QueryDoubleAttribute(XML_HDG, &dHdg);
        iChecker += pGeometryNode->QueryDoubleAttribute(XML_LENGTH, &dLength);
        iChecker += pGeometryNode->QueryDoubleAttribute(XML_S, &dS);
        iChecker += pGeometryNode->QueryDoubleAttribute(XML_X, &dX);
        iChecker += pGeometryNode->QueryDoubleAttribute(XML_Y, &dY);

        const TiXmlElement *pGeometryTypeNode = pGeometryNode->FirstChildElement();
        if (nullptr == pGeometryTypeNode)
        {
            std::string strErrMsg = "geometry type node is error";
            return -1;
        }

        SCoefficients extend;
        std::string strGeometryType = pGeometryTypeNode->Value();

        if (strGeometryType == XML_ARC)
        {
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_CURVATURE, &extend.a);
        }
        else if (strGeometryType == XML_SPIRAL)
        {
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_CURVSTART, &extend.a);
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_CURVEND, &extend.b);
        }
        else if (strGeometryType == XML_POLY3)
        {
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_A, &extend.a);
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_B, &extend.b);
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_C, &extend.c);
            iChecker += pGeometryTypeNode->QueryDoubleAttribute(XML_D, &extend.d);
        }
        else
        {
            assert("other geometry");
        }

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "geometry node is error";
            return -1;
        }

        SGeometry geometry;
        geometry.hdg = dHdg;
        geometry.length = dLength;
        geometry.s = dS;
        geometry.x = dX;
        geometry.y = dY;
        geometry.type = strGeometryType;
        geometry.extend = extend;

        vecGeometry.push_back(geometry);

        pGeometryNode = pGeometryNode->NextSiblingElement(XML_GEOMETRY);
    }

    return 0;
}

int MapParser::parsePlanView(const TiXmlElement &xmlNode, PlanView &planView)
{
    const TiXmlElement *pRoadPlanViewNode = xmlNode.FirstChildElement(XML_PLANVIEW);
    while (pRoadPlanViewNode != nullptr)
    {
        int iRet = parseGeometry(*pRoadPlanViewNode, planView.qvecGeometry);
        if (iRet != 0)
        {
            std::string strErrMsg = "road planView node is error";
            return -1;
        }

        pRoadPlanViewNode = pRoadPlanViewNode->NextSiblingElement(XML_PLANVIEW);
    }

    return 0;
}

int MapParser::parseElevation(const TiXmlElement &xmlNode, QVector<SElevation> &vecElevation)
{
    const TiXmlElement *pelevationNode = xmlNode.FirstChildElement(XML_ELEVATION);
    while (pelevationNode != nullptr)
    {
        double dS = 0.0;
        double dA = 0.0;
        double dB = 0.0;
        double dC = 0.0;
        double dD = 0.0;

        int iChecker = pelevationNode->QueryDoubleAttribute(XML_S, &dS);
        iChecker += pelevationNode->QueryDoubleAttribute(XML_A, &dA);
        iChecker += pelevationNode->QueryDoubleAttribute(XML_B, &dB);
        iChecker += pelevationNode->QueryDoubleAttribute(XML_C, &dC);
        iChecker += pelevationNode->QueryDoubleAttribute(XML_D, &dD);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "elevation node is error";
            return -1;
        }

        SElevation elevation;
        elevation.s = dS;
        elevation.coefficients.a = dA;
        elevation.coefficients.b = dB;
        elevation.coefficients.c = dC;
        elevation.coefficients.d = dD;

        vecElevation.push_back(elevation);

        pelevationNode = pelevationNode->NextSiblingElement(XML_ELEVATION);
    }

    return 0;
}

int MapParser::parseElevationProfile(const TiXmlElement &xmlNode, ElevationProfile &elevationProfile)
{
    const TiXmlElement *pElevationProfileNode = xmlNode.FirstChildElement(XML_ELEVATIONPROFILE);
    while (pElevationProfileNode != nullptr)
    {
        int iRet = parseElevation(*pElevationProfileNode, elevationProfile.qvecElevation);
        if (iRet != 0)
        {
            std::string strErrMsg = "road elevationProfile node is error";
            return -1;
        }

        pElevationProfileNode = pElevationProfileNode->NextSiblingElement(XML_ELEVATIONPROFILE);
    }

    return 0;
}

int MapParser::parseLaneOffset(const TiXmlElement &xmlNode, QVector<SLaneOffset> &vecLaneOffset)
{
    const TiXmlElement *pLaneOffsetNode = xmlNode.FirstChildElement(XML_LANEOFFSET);
    while (pLaneOffsetNode != nullptr)
    {
        double dS = 0.0;
        double dA = 0.0;
        double dB = 0.0;
        double dC = 0.0;
        double dD = 0.0;

        int iChecker = pLaneOffsetNode->QueryDoubleAttribute(XML_S, &dS);
        iChecker += pLaneOffsetNode->QueryDoubleAttribute(XML_A, &dA);
        iChecker += pLaneOffsetNode->QueryDoubleAttribute(XML_B, &dB);
        iChecker += pLaneOffsetNode->QueryDoubleAttribute(XML_C, &dC);
        iChecker += pLaneOffsetNode->QueryDoubleAttribute(XML_D, &dD);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "laneOffset node is error";
            return -1;
        }

        SLaneOffset laneOffset;
        laneOffset.s = dS;
        laneOffset.coefficients.a = dA;
        laneOffset.coefficients.b = dB;
        laneOffset.coefficients.c = dC;
        laneOffset.coefficients.d = dD;

        vecLaneOffset.push_back(laneOffset);

        pLaneOffsetNode = pLaneOffsetNode->NextSiblingElement(XML_LANEOFFSET);
    }

    return 0;
}

int MapParser::parseLaneLink(const TiXmlElement &xmlNode, LaneLink &laneLink)
{
    const TiXmlElement *pLaneLinkNode = xmlNode.FirstChildElement(XML_LINK);
    while (pLaneLinkNode != nullptr)
    {
        const TiXmlElement *pLaneLinkPreNode = pLaneLinkNode->FirstChildElement(XML_PREDECESSOR);
        int iChecker = TIXML_SUCCESS;
        if (nullptr == pLaneLinkPreNode)
        {
            std::string strErrMsg = "lane link pre node is null";
        }
        else
        {
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneLinkPreNode, XML_ID, laneLink.predecessor.id);
        }

        const TiXmlElement *pLaneLinkSucNode = pLaneLinkNode->FirstChildElement(XML_SUCCESSOR);
        if (nullptr == pLaneLinkSucNode)
        {
            std::string strErrMsg = "lane link suc node is null";
        }
        else
        {
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneLinkSucNode, XML_ID, laneLink.successor.id);
        }

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "Error parsing lane link";
            return -1;
        }

        pLaneLinkNode = pLaneLinkNode->NextSiblingElement(XML_LINK);
    }

    return 0;
}

int MapParser::parseLane(const TiXmlElement &xmlNode, QVector<SLane> &vecLanes)
{
    const TiXmlElement *pLaneNode = xmlNode.FirstChildElement(XML_LANE);
    while (pLaneNode != nullptr)
    {
        std::string strLaneID;
        std::string strLaneType;
        std::string strLaneLevel;
        int iChecker = UtilXmlParser::queryStringAttribute(*pLaneNode, XML_ID, strLaneID);
        iChecker += UtilXmlParser::queryStringAttribute(*pLaneNode, XML_TYPE, strLaneType);
        iChecker += UtilXmlParser::queryStringAttribute(*pLaneNode, XML_LEVEL, strLaneLevel);

        // link
        LaneLink link;
        const TiXmlElement *pLaneLinkNode = pLaneNode->FirstChildElement(XML_LINK);
        if (nullptr == pLaneLinkNode)
        {
            std::string strErrMsg = "lane node no link node";
        }
        else
        {
            link.bExist = true;
            iChecker += parseLaneLink(*pLaneNode, link);
        }

        // width
        Width width;
        const TiXmlElement *pLaneWidthNode = pLaneNode->FirstChildElement(XML_WIDTH);
        if (nullptr == pLaneWidthNode)
        {
            std::string strErrMsg = "lane node no width node";
        }
        else
        {
            width.bExist = true;
            iChecker += pLaneWidthNode->QueryDoubleAttribute(XML_A, &width.coefficients.a);
            iChecker += pLaneWidthNode->QueryDoubleAttribute(XML_B, &width.coefficients.b);
            iChecker += pLaneWidthNode->QueryDoubleAttribute(XML_C, &width.coefficients.c);
            iChecker += pLaneWidthNode->QueryDoubleAttribute(XML_D, &width.coefficients.d);
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneWidthNode, XML_SOFFSET, width.sOffset);
        }

        // roadMark
        RoadMark roadMark;
        const TiXmlElement *pLaneRoadMarkNode = pLaneNode->FirstChildElement(XML_ROADMARK);
        if (nullptr == pLaneRoadMarkNode)
        {
            std::string strErrMsg = "lane node no roadMark node";
//            return -1;  // 兼容8字地图
        }
        else
        {
            roadMark.bExist = true;
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneRoadMarkNode, XML_COLOR, roadMark.color);
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneRoadMarkNode, XML_SOFFSET, roadMark.sOffset);
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneRoadMarkNode, XML_TYPE, roadMark.type);
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneRoadMarkNode, XML_WEIGHT, roadMark.weight);
        }

        // height
        Height height;
        const TiXmlElement *pLaneHeightNode = pLaneNode->FirstChildElement(XML_HEIGHT);
        if (nullptr == pLaneHeightNode)
        {
            std::string strErrMsg = "lane node no roadMark node";
        }
        else
        {
            height.bExist = true;
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneHeightNode, XML_SOFFSET, height.sOffset);
            iChecker += (
                            UtilXmlParser::queryStringAttribute(*pLaneHeightNode, XML_INNER, height.inner) &
                            UtilXmlParser::queryStringAttribute(*pLaneHeightNode, XML_HEIGHTINNER, height.inner)
                        );
            iChecker += (
                            UtilXmlParser::queryStringAttribute(*pLaneHeightNode, XML_OUTER, height.outer) &
                            UtilXmlParser::queryStringAttribute(*pLaneHeightNode, XML_HEIGHTOUTER, height.outer)
                        );
        }

        // speed
        Speed speed;
        const TiXmlElement *pLaneSpeedNode = pLaneNode->FirstChildElement(XML_SPEED);
        if (nullptr == pLaneSpeedNode)
        {
            std::string strErrMsg = "lane node no speed node";
        }
        else
        {
            speed.bExist = true;
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneSpeedNode, XML_SOFFSET, speed.sOffset);
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneSpeedNode, XML_MAX, speed.max);
        }

        // userData
        UserData userData;
        const TiXmlElement *pLaneUserDataNode = pLaneNode->FirstChildElement(XML_USERDATA);
        if (nullptr == pLaneUserDataNode)
        {
            std::string strErrMsg = "lane node no userData node";
        }
        else
        {
            userData.bExist = true;
            iChecker += UtilXmlParser::queryStringAttribute(*pLaneUserDataNode, XML_CODE, userData.code);

            // style
            const TiXmlElement *pUserDataStyleNode = pLaneUserDataNode->FirstChildElement(XML_STYLE);
            if (nullptr == pUserDataStyleNode)
            {
                std::string strErrMsg = "userData node no style node";
            }
            else
            {
                userData.style.bExist = true;
                iChecker += UtilXmlParser::queryStringAttribute(*pUserDataStyleNode, XML_SOFFSET, userData.style.sOffset);
                iChecker += UtilXmlParser::queryStringAttribute(*pUserDataStyleNode, XML_LANESTYLE, userData.style.laneStyle);
                iChecker += UtilXmlParser::queryStringAttribute(*pUserDataStyleNode, XML_MAPPING, userData.style.mapping);
            }

            // fillet
            const TiXmlElement *pUserDataFilletNode = pLaneUserDataNode->FirstChildElement(XML_FILLET);
            if (nullptr == pUserDataFilletNode)
            {
                std::string strErrMsg = "userData node no fillet node";
            }
            else
            {
                userData.fillet.bExist = true;
                iChecker += UtilXmlParser::queryStringAttribute(*pUserDataFilletNode, XML_POS, userData.fillet.pos);
                iChecker += UtilXmlParser::queryStringAttribute(*pUserDataFilletNode, XML_STYLE, userData.fillet.style);
                iChecker += UtilXmlParser::queryStringAttribute(*pUserDataFilletNode, XML_ID, userData.fillet.id);
            }
        }

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "lane node is error";
            return -1;
        }

        SLane lane;
        lane.id = strLaneID;
        lane.type = strLaneType;
        lane.level = strLaneLevel;
        lane.link = link;
        lane.width = width;
        lane.roadMark = roadMark;
        lane.speed = speed;
        lane.height = height;
        lane.userData = userData;

        vecLanes.push_back(lane);

        pLaneNode = pLaneNode->NextSiblingElement(XML_LANE);
    }

    return 0;
}

int MapParser::parseLaneSection(const TiXmlElement &xmlNode, QVector<SLaneSection> &vecLaneSections)
{
    const TiXmlElement *pLaneSectionNode = xmlNode.FirstChildElement(XML_LANESECTION);
    while (pLaneSectionNode != nullptr)
    {
        double dS = 0.0;

        int iChecker = pLaneSectionNode->QueryDoubleAttribute(XML_S, &dS);

        // left
        const TiXmlElement *pLeftNode = pLaneSectionNode->FirstChildElement(XML_LEFT);

        Layout leftLayout;

        if (nullptr == pLeftNode)
        {
            std::string strErrMsg = "laneSection no left node";
        }
        else
        {
            leftLayout.bExist = true;
            iChecker += parseLane(*pLeftNode, leftLayout.qvecLane);
        }

        // center
        const TiXmlElement *pCenterNode = pLaneSectionNode->FirstChildElement(XML_CENTER);
        if (nullptr == pCenterNode)
        {
            std::string strErrMsg = "laneSection no left node";
            return -1;
        }

        Layout centerLayout;
        centerLayout.bExist = true;
        iChecker += parseLane(*pCenterNode, centerLayout.qvecLane);

        // right
        const TiXmlElement *pRightNode = pLaneSectionNode->FirstChildElement(XML_RIGHT);

        Layout rightLayout;

        if (nullptr == pRightNode)
        {
            std::string strErrMsg = "laneSection no left node";
//            return -1; // 兼容德国地图
        }
        else
        {
            rightLayout.bExist = true;
            iChecker += parseLane(*pRightNode, rightLayout.qvecLane);
        }

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "laneSection node is error";
            return -1;
        }

        SLaneSection laneSection;
        laneSection.s = dS;
        laneSection.left = leftLayout;
        laneSection.center = centerLayout;
        laneSection.right = rightLayout;

        vecLaneSections.push_back(laneSection);

        pLaneSectionNode = pLaneSectionNode->NextSiblingElement(XML_LANESECTION);
    }

    return 0;
}

int MapParser::parseRoadLanes(const TiXmlElement &xmlNode, Lanes &lanes)
{
    const TiXmlElement *pLanesNode = xmlNode.FirstChildElement(XML_LANES);
    while (pLanesNode != nullptr)
    {
        int iRet = parseLaneOffset(*pLanesNode, lanes.qvecLaneOffset);
        iRet += parseLaneSection(*pLanesNode, lanes.qvecLaneSection);

        if (iRet != 0)
        {
            std::string strErrMsg = "road lanes node is error";
            return -1;
        }

        pLanesNode = pLanesNode->NextSiblingElement(XML_LANES);
    }

    return 0;
}

int MapParser::parseObject(const TiXmlElement &xmlNode, QVector<Object> &vecObject)
{
    const TiXmlElement *pObjectNode = xmlNode.FirstChildElement(XML_OBJECT);
    while (pObjectNode != nullptr)
    {
        Object object;
        int iChecker = UtilXmlParser::queryStringAttribute(*pObjectNode, XML_ID, object.id);
        iChecker += UtilXmlParser::queryStringAttribute(*pObjectNode, XML_TYPE, object.type);
        iChecker += UtilXmlParser::queryStringAttribute(*pObjectNode, XML_NAME, object.name);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_S, &object.s);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_T, &object.t);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_ZOFFSET, &object.zOffset);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_LENGTH, &object.length);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_WIDTH, &object.width);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_HEIGHT, &object.height);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_HDG, &object.hdg);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_PITCH, &object.pitch);
        iChecker += pObjectNode->QueryDoubleAttribute(XML_ROLL, &object.roll);

        const TiXmlElement *pRepeatNode = pObjectNode->FirstChildElement(XML_REPEAT);
        if (pRepeatNode != nullptr)
        {
            object.repeat.bExist = true;
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_S, &object.repeat.s);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_LENGTH, &object.repeat.length);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_DISTANCE, &object.repeat.distance);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_TSTART, &object.repeat.tStart);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_TEND, &object.repeat.tEnd);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_WIDTHSTART, &object.repeat.widthStart);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_WIDTHEND, &object.repeat.widthEnd);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_HEIGHTSTART, &object.repeat.heightStart);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_HEIGHTEND, &object.repeat.heightEnd);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_ZOFFSETSTART, &object.repeat.zOffsetStart);
            iChecker += pRepeatNode->QueryDoubleAttribute(XML_ZOFFSETEND, &object.repeat.zOffsetEnd);
        }
        else
        {
            std::string strTips = "object node no repeat node";
        }

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "object node is error";
//            return -1;
        }

        vecObject.push_back(object);

        pObjectNode = pObjectNode->NextSiblingElement(XML_OBJECT);
    }

    return 0;
}

int MapParser::parseRoadObjects(const TiXmlElement &xmlNode, Objects &objects)
{
    const TiXmlElement *pObjectsNode = xmlNode.FirstChildElement(XML_OBJECTS);
    while (pObjectsNode != nullptr)
    {
        const TiXmlElement *pObjectNode = pObjectsNode->FirstChildElement(XML_OBJECT);
        int iRet = 0;
        if (nullptr == pObjectNode)
        {
            std::string strErrMsg = "objects node no object node";
        }
        else
        {
            iRet += parseObject(*pObjectsNode, objects.qvecObject);
        }

        if (iRet != 0)
        {
            std::string strErrMsg = "object node is error";
            return -1;
        }

        pObjectsNode = pObjectsNode->NextSiblingElement(XML_OBJECTS);
    }

    return 0;
}

int MapParser::parseSignal(const TiXmlElement &xmlNode, QVector<Signal> &vecSignal)
{
    const TiXmlElement *pSignalNode = xmlNode.FirstChildElement(XML_SIGNAL);
    while (pSignalNode != nullptr)
    {
        Signal signal;
        int iChecker = pSignalNode->QueryDoubleAttribute(XML_S, &signal.s);
        iChecker += pSignalNode->QueryDoubleAttribute(XML_T, &signal.t);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_ID, signal.id);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_NAME, signal.name);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_DYNAMIC, signal.dynamic);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_ORIENTATION, signal.orientation);
        iChecker += pSignalNode->QueryDoubleAttribute(XML_ZOFFSET, &signal.zOffset);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_TYPE, signal.type);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_COUNTRY, signal.country);
        iChecker += UtilXmlParser::queryStringAttribute(*pSignalNode, XML_SUBTYPE, signal.subtype);
//        iChecker += pSignalNode->QueryDoubleAttribute(XML_HOFFSET, &signal.hOffset); // 兼容8字地图
//        iChecker += pSignalNode->QueryDoubleAttribute(XML_PITCH, &signal.pitch);
//        iChecker += pSignalNode->QueryDoubleAttribute(XML_ROLL, &signal.roll);
//        iChecker += pSignalNode->QueryDoubleAttribute(XML_HEIGHT, &signal.height);
//        iChecker += pSignalNode->QueryDoubleAttribute(XML_WIDTH, &signal.width);

        const TiXmlElement *pUserDataNode = pSignalNode->FirstChildElement(XML_USERDATA);
        if (pUserDataNode != nullptr)
        {
            signal.userData.bExist = true;
            iChecker += UtilXmlParser::queryStringAttribute(*pUserDataNode, XML_CODE, signal.userData.code);
            iChecker += pUserDataNode->QueryDoubleAttribute(XML_VALUE, &signal.userData.value);
        }
        else
        {
            std::string strTips = "signal node no userData node";
        }


        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "signal node is error";
            return -1;
        }

        vecSignal.push_back(signal);

        pSignalNode = pSignalNode->NextSiblingElement(XML_SIGNAL);
    }

    return 0;
}

int MapParser::parseRoadSignals(const TiXmlElement &xmlNode, Signals &roadSignals)
{
    const TiXmlElement *pSignalsNode = xmlNode.FirstChildElement(XML_SIGNALS);
    while (pSignalsNode != nullptr)
    {
        const TiXmlElement *pSignalNode = pSignalsNode->FirstChildElement(XML_SIGNAL);
        int iRet = 0;
        if (nullptr == pSignalNode)
        {
            std::string strErrMsg = "signals node no signal node";
        }
        else
        {
            iRet += parseSignal(*pSignalsNode, roadSignals.qvecSignal);
        }

        if (iRet != 0)
        {
            std::string strErrMsg = "signal node is error";
            return -1;
        }

        pSignalsNode = pSignalsNode->NextSiblingElement(XML_SIGNALS);
    }

    return 0;
}

int MapParser::parseControl(const TiXmlElement &xmlNode, QVector<Control> &vecControl)
{
    const TiXmlElement *pControlNode = xmlNode.FirstChildElement(XML_CONTROL);
    while (pControlNode != nullptr)
    {
        Control control;
        int iChecker = UtilXmlParser::queryStringAttribute(*pControlNode, XML_SIGNALID, control.signalId);
        iChecker += UtilXmlParser::queryStringAttribute(*pControlNode, XML_TYPE, control.type);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "control node is error";
            return -1;
        }

        vecControl.push_back(control);

        pControlNode = pControlNode->NextSiblingElement(XML_CONTROL);
    }

    return 0;
}

int MapParser::parseController(const TiXmlElement &xmlNode, QVector<SController> &vecController)
{
    const TiXmlElement *pControllerNode = xmlNode.FirstChildElement(XML_CONTROLLER);
    while (pControllerNode != nullptr)
    {
        SController controller;
        int iChecker = UtilXmlParser::queryStringAttribute(*pControllerNode, XML_ID, controller.id);
        iChecker += parseControl(*pControllerNode, controller.qvecControl);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "controller node is error";
            return -1;
        }

        vecController.push_back(controller);

        pControllerNode = pControllerNode->NextSiblingElement(XML_CONTROLLER);
    }

    return 0;
}

int MapParser::parseConnectLaneLink(const TiXmlElement &xmlNode, QVector<ConnectLaneLink> &vecConnectLaneLink)
{
    const TiXmlElement *pLaneLinkNode = xmlNode.FirstChildElement(XML_LANELINK);
    while (pLaneLinkNode != nullptr)
    {
        ConnectLaneLink laneLink;
        int iChecker = UtilXmlParser::queryStringAttribute(*pLaneLinkNode, XML_FROM, laneLink.from);
        iChecker += UtilXmlParser::queryStringAttribute(*pLaneLinkNode, XML_TO, laneLink.to);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "laneLink node is error";
            return -1;
        }

        vecConnectLaneLink.push_back(laneLink);

        pLaneLinkNode = pLaneLinkNode->NextSiblingElement(XML_LANELINK);
    }

    return 0;
}

int MapParser::parseConnection(const TiXmlElement &xmlNode, QVector<Connection> &vecConnection)
{
    const TiXmlElement *pConnectionNode = xmlNode.FirstChildElement(XML_CONNECTION);
    while (pConnectionNode != nullptr)
    {
        Connection connection;
        int iChecker = UtilXmlParser::queryStringAttribute(*pConnectionNode, XML_ID, connection.id);
        iChecker += UtilXmlParser::queryStringAttribute(*pConnectionNode, XML_INCOMINGROAD, connection.incomingRoad);
        iChecker += UtilXmlParser::queryStringAttribute(*pConnectionNode, XML_CONNECTINGROAD, connection.connectingRoad);
        iChecker += UtilXmlParser::queryStringAttribute(*pConnectionNode, XML_CONTACTPOINT, connection.contactPoint);
        iChecker += parseConnectLaneLink(*pConnectionNode, connection.qvecLaneLink);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "connection node is error";
            return -1;
        }

        vecConnection.push_back(connection);

        pConnectionNode = pConnectionNode->NextSiblingElement(XML_CONNECTION);
    }

    return 0;
}

int MapParser::parseJunctionController(const TiXmlElement &xmlNode, QVector<JunctionController> &vecController)
{
    const TiXmlElement *pControllerNode = xmlNode.FirstChildElement(XML_CONTROLLER);
    while (pControllerNode != nullptr)
    {
        JunctionController controller;
        int iChecker = UtilXmlParser::queryStringAttribute(*pControllerNode, XML_ID, controller.id);
        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "controller node is error";
            return -1;
        }

        vecController.push_back(controller);

        pControllerNode = pControllerNode->NextSiblingElement(XML_CONTROLLER);
    }

    return 0;
}

int MapParser::parserJunction(const TiXmlElement &xmlNode, QVector<Junction> &vecJunction)
{
    const TiXmlElement *pJunctionNode = xmlNode.FirstChildElement(XML_JUNCTION);
    while (pJunctionNode != nullptr)
    {
        Junction junction;
        int iChecker = UtilXmlParser::queryStringAttribute(*pJunctionNode, XML_ID, junction.id);
        iChecker += UtilXmlParser::queryStringAttribute(*pJunctionNode, XML_NAME, junction.name);
        iChecker += parseConnection(*pJunctionNode, junction.qvecConnection);
        iChecker += parseJunctionController(*pJunctionNode, junction.qvecController);

        if (iChecker != TIXML_SUCCESS)
        {
            std::string strErrMsg = "junction node is error";
            return -1;
        }

        vecJunction.push_back(junction);

        pJunctionNode = pJunctionNode->NextSiblingElement(XML_JUNCTION);
    }

    return 0;
}
